﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using UnityEditor;
using UnityEngine;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using UnityEngine.UI;
using Debug = UnityEngine.Debug;
using Object = UnityEngine.Object;
using System.Threading;
using Framework.Utils;
using Unity.Plastic.Newtonsoft.Json;

/*编辑器资源工具*/
public class AssetsTool : AssetPostprocessor
{
    static readonly string DEFAULTS_KEY = "DEFAULTS_DONE";
    static readonly uint DEFAULTS_VERSION = 2;
    static readonly string HadBeenModified = "HadBeenModified";

    public bool IsAssetProcessed
    {
        get 
        {
            return AssetDatabase.GetLabels(assetImporter).Contains(HadBeenModified);
        }
        set
        {
            AssetDatabase.SetLabels(assetImporter, new string[] { HadBeenModified });
        }
        //get
        //{
        //    foreach (var item in AssetDatabase.GetLabels(assetImporter))
        //    {
        //        if (item.Equals(HadBeenModified))
        //        {
        //            return true;
        //        }
        //    }
        //    return false;
        //    //string key = string.Format("{0}_{1}", DEFAULTS_KEY, DEFAULTS_VERSION);
        //    //return assetImporter.userData.Contains(key);
        //}
        //set
        //{
        //    Debug.Log("设置图片->" + assetImporter.assetPath);
        //    List<string> str = AssetDatabase.GetLabels(assetImporter).ToList<string>();
        //    str.Add(HadBeenModified);
        //    AssetDatabase.SetLabels(assetImporter, str.ToArray());
        //}
    }
    private void OnPreprocessTexture()
    {
        TextureImporter importer = (TextureImporter)assetImporter;
        //Debug.Log("发现导入图片->" + importer.assetPath);

        if (!IsAssetProcessed &&
            (importer.assetPath.Contains("UI_Tex") || importer.assetPath.ToLower().Contains("zwTest".ToLower()))
            )
        {
            importer.textureType = TextureImporterType.Sprite;
            importer.mipmapEnabled = false;
            importer.SaveAndReimport();
            IsAssetProcessed = true;
        }
    }
    void OnPreprocessModel()
    {
        //ModelImporter importer = (ModelImporter)assetImporter;
        AssetImporter importer = (AssetImporter)assetImporter;
        Debug.Log("发现导入模型->" + importer.assetPath);
    }

    void OnPreprocessAnimation()
    {
        AssetImporter importer = (AssetImporter)assetImporter;
        Debug.Log("发现导入动画->" + importer.assetPath);
    }

    void OnPreprocessAudio()
    {
        //VideoClipImporter importer = (VideoClipImporter)assetImporter;
        AudioImporter importer = (AudioImporter)assetImporter;
        if (!IsAssetProcessed)
        {
            //Debug.Log("发现导入音频->" + importer.assetPath);
            importer.forceToMono = true;
            EditorUtility.SetDirty(importer);
            importer.SaveAndReimport();
            IsAssetProcessed = true;
        }
    }
}

public class FindResWindows : EditorWindow
{
    // [MenuItem("Assets/查看所选资源, 有谁在引用", false, 1)]

    [MenuItem("Assets/资源/查找资源所有引用", false, 36)]
    private static void FindReferences()
    {
        Object[] SelectedAsset = Selection.GetFiltered(typeof(Object), SelectionMode.Assets);
        if (SelectedAsset.Length == 0)
        {
            Debug.Log("未选择有效对象");
            Debug.Log("=======================end==============================");
            return;
        }

        Debug.LogWarning("查找资源所有引用 Start");
        for (int i = 0; i < SelectedAsset.Length; i++)
        {
            string path = AssetDatabase.GetAssetPath(SelectedAsset[i]);
            string[] deps = AssetDatabase.GetDependencies(path);
            for (int j = 0; j < deps.Length; j++)
            {
                Debug.Log(deps[j], context: AssetDatabase.LoadAssetAtPath<Object>(deps[j]));
            }
        }

        Debug.LogWarning("查找资源所有引用 End");

    }

    [MenuItem("Assets/资源/查找资源所有引用(剔除非直接依赖)", false, 37)]
    private static void FindReferences2()
    {
        Object[] SelectedAsset = Selection.GetFiltered(typeof(Object), SelectionMode.Assets);
        if (SelectedAsset.Length == 0)
        {
            Debug.Log("未选择有效对象");
            Debug.Log("=======================end==============================");
            return;
        }

        Debug.LogWarning("查找资源所有引用 Start");
        for (int i = 0; i < SelectedAsset.Length; i++)
        {
            string path = AssetDatabase.GetAssetPath(SelectedAsset[i]);
            string[] dependencyArray = AssetDatabase.GetDependencies(path);
            //排除掉非直接依赖
            List<string> directDependAssetsLst = new List<string>();
            List<string> noDirectDependAssetsLst = new List<string>(); //非直接依赖文件路径
            if (dependencyArray != null)
            {
                foreach (var d in dependencyArray)
                {
                    if (d.EndsWith(".prefab") && d != path)
                    {
                        directDependAssetsLst.Add(d);
                        string[] tempDepends = AssetDatabase.GetDependencies(d);
                        foreach (var temp in tempDepends)
                        {
                            if (noDirectDependAssetsLst.Contains(temp))
                            {
                                continue;
                            }

                            noDirectDependAssetsLst.Add(temp);
                        }
                    }
                }

                //剔除非直接依赖资源
                foreach (var d in dependencyArray)
                {
                    if (noDirectDependAssetsLst.Contains(d))
                    {
                        continue;
                    }

                    directDependAssetsLst.Add(d);
                }
            }

            for (int j = 0; j < directDependAssetsLst.Count; j++)
            {
                Debug.Log(directDependAssetsLst[j],
                    context: AssetDatabase.LoadAssetAtPath<Object>(directDependAssetsLst[j]));
            }
        }

        Debug.LogWarning("查找资源所有引用 End");

    }

    [MenuItem("Assets/资源/查找资源是否被引用", true)]
    static private bool FindReferencesInProjectCheck()
    {
        Object[] SelectedAsset = Selection.GetFiltered(typeof(Object), SelectionMode.Assets);
        //此处添加需要命名的资源后缀名,注意大小写。
        string[] Filtersuffix = new string[]
            {".prefab", ".mat", ".dds", ".png", ".jpg", ".shader", ".csv", ".wav", ".mp3"};
        if (SelectedAsset.Length == 0)
        {
            return false;
        }

        return true;
    }

    [MenuItem("Assets/资源/查找资源是否被引用", false, 25)]
    static private void FindReferencesInProject()
    {
        Debug.Log("=======================start=============================");
        EditorSettings.serializationMode = SerializationMode.ForceText;

        Object[] SelectedAsset = Selection.GetFiltered(typeof(Object), SelectionMode.Assets);
        //此处添加需要命名的资源后缀名,注意大小写。
        string[] Filtersuffix = new string[]
            {".prefab", ".mat", ".dds", ".png", ".jpg", ".shader", ".csv", ".wav", ".mp3"};
        if (SelectedAsset.Length == 0)
        {
            Debug.Log("未选择有效对象");
            Debug.Log("=======================end==============================");
            return;
        }

        List<string> withoutExtensions = new List<string>() {".prefab", ".unity", ".mat", ".asset"};
        string[] files = Directory.GetFiles(Application.dataPath, "*.*", SearchOption.AllDirectories)
            .Where(s => withoutExtensions.Contains(Path.GetExtension(s).ToLower())).ToArray();
        foreach (Object tmpFolder in SelectedAsset)
        {
            string path = AssetDatabase.GetAssetPath(tmpFolder);
            if (!string.IsNullOrEmpty(path))
            {
                long timeStamp = Stopwatch.GetTimestamp();
                string guid = AssetDatabase.AssetPathToGUID(path);
                System.Text.ASCIIEncoding ASCII = new System.Text.ASCIIEncoding();
                Byte[] BytesMessage = ASCII.GetBytes(guid);

                int num = 0;
                for (var i = 0; i < files.Length; ++i)
                {
                    string file = files[i];
                    //显示进度条
                    EditorUtility.DisplayProgressBar("匹配资源", "正在匹配资源中...", 1.0f * i / files.Length);
                    // File.ReadAllBytes(file).Contains(BytesMessage)
                    // if (Regex.IsMatch(File.ReadAllBytes(file), BytesMessage))
                    if (IndexesOf(File.ReadAllBytes(file), BytesMessage) != -1)
                    {
                        Debug.Log(file, AssetDatabase.LoadAssetAtPath<Object>(GetRelativeAssetsPath(file)));
                        num++;
                    }
                }

                string timeStr = string.Format("GetDependencies cost {0} ms.",
                    (Stopwatch.GetTimestamp() - timeStamp) * 1000 / Stopwatch.Frequency);
                
                if (num == 0)
                {
                    Debug.LogError(tmpFolder.name + "     匹配到" + num + "个" + "\n" + timeStr, tmpFolder);
                }
                else if (num == 1)
                {
                    Debug.Log(tmpFolder.name + "     匹配到" + num + "个" + "\n" + timeStr, tmpFolder);
                }
                else
                {
                    Debug.LogWarning(tmpFolder.name + "     匹配到" + num + "个" + "\n" + timeStr, tmpFolder);
                }

                Debug.Log("=======================end==============================");
            }
        }

        EditorUtility.ClearProgressBar();
    }

    public static int FindReferencesInFolderCount = 0;
    [MenuItem("Assets/资源/查找文件夹未被引用的资源有哪些", false, 26)]
    static public void FindReferencesInFolder()
    {
        //Stopwatch sw = new Stopwatch();
        //sw.Start();
        Debug.LogWarning("=======================正在匹配资源中=============================");
        Object[] SelectedAsset = Selection.GetFiltered(typeof(Object), SelectionMode.Assets);
        List<string> withoutExtensions = new List<string>() {".prefab", ".unity", ".mat", ".asset"};
        string[] files = Directory.GetFiles(Application.dataPath, "*.*", SearchOption.AllDirectories)
            .Where(s => withoutExtensions.Contains(Path.GetExtension(s).ToLower())).ToArray();

        for (int j = 0; j < SelectedAsset.Length; j++)
        {
            Object tmpFolder = SelectedAsset[j];
            string filepath = AssetDatabase.GetAssetPath(tmpFolder);
            Debug.Log("select filePath:" + filepath);
            List<string> tempList = new List<string>();
            GetDirFiles(filepath, tempList);
            for (int k = 0; k < tempList.Count; k++)
            {
                string tempFilePath = tempList[k];
                if (!File.Exists(tempFilePath))
                {
                    continue;
                }

                //显示进度条
                float percent = 1.0f * (k + 1) / tempList.Count;
                string fms = string.Format("({0}/{1})", k + 1, tempList.Count);
                EditorUtility.DisplayProgressBar("匹配资源", "正在匹配资源中..." + fms, percent);

                FindReferencesInFolderCount = tempList.Count;
                //MatchGuid(files, tempFilePath);
                FileMatch f = new FileMatch(files, tempFilePath, AssetDatabase.AssetPathToGUID(tempFilePath));
                Thread t = new Thread(new ParameterizedThreadStart(MatchGuid));
                t.Start(f);
            }

        }

        EditorUtility.ClearProgressBar();
        //sw.Stop();
        //Debug.Log("当前搜索耗时---->" + (sw.ElapsedMilliseconds / 1000.0) + "s");
    }
    public class FileMatch {
        public string[] files;
        public string tempFilePath;
        public string guid;
        public FileMatch(string[] files, string tempFilePath,string guid)
        {
            this.files = files;
            this.tempFilePath = tempFilePath;
            this.guid = guid;
        }
    }
    private static void MatchGuid(object obj)
    {
        Stopwatch sw = new Stopwatch();
        sw.Start();
        FileMatch fileMatch = (FileMatch)obj;
        int num = 0;
        string guid = fileMatch.guid;
        for (var i = 0; i < fileMatch.files.Length; ++i)
        {
            string str = fileMatch.files[i];
            if (str == null)
            {
                Debug.Log("错误索引->" + i);
            }
            else if (Regex.IsMatch(File.ReadAllText(str), guid))
            {
                num++;
            }
        }

        if (num == 0)
        {
            Debug.LogWarning(fileMatch.tempFilePath);
            //Debug.Log(fileMatch.tempFilePath, AssetDatabase.LoadAssetAtPath<Object>(GetRelativeAssetsPath(fileMatch.tempFilePath)));
        }
        else
        {
            Debug.Log("该资源被引用了->" + fileMatch.tempFilePath);
        }
        sw.Stop();
        lock ((object)FindReferencesInFolderCount)
        {
            FindReferencesInFolderCount--;
            if (FindReferencesInFolderCount <= 0)
            {
                sw.Stop();
                Debug.Log("当前搜索耗时---->" + (sw.ElapsedMilliseconds / 1000.0) + "s");
                Debug.LogWarning("=======================匹配结束=============================");
            }
        }
    }

    public static void MatchGuid(string[] files, string tempFilePath)
    {
        int num = 0;
        string guid = AssetDatabase.AssetPathToGUID(tempFilePath);
        for (var i = 0; i < files.Length; ++i)
        {
            if (Regex.IsMatch(File.ReadAllText(files[i]), guid))
            {
                num++;
            }
        }

        if (num == 0)
        {
            Debug.Log(tempFilePath, AssetDatabase.LoadAssetAtPath<Object>(GetRelativeAssetsPath(tempFilePath)));
        }

    }

    [MenuItem("Packager/移除模型原始材质球", false, 26)]
    public static void ModelRemoveMat()
    {
        string[] files = Directory.GetFiles(Application.dataPath + "/GameAssets/", "*.*", SearchOption.AllDirectories);

        foreach(var file in files)
        {
            if(file.EndsWith(".fbx") || file.EndsWith(".FBX"))
            {
                int idx = file.IndexOf("Assets/");
                string p = file.Substring(idx);
                ModelImporter importer = AssetImporter.GetAtPath(p) as ModelImporter;
                if(importer.materialImportMode == ModelImporterMaterialImportMode.None)
                {
                    continue;
                }
                Debug.Log("处理模型-->" + p);
                importer.materialImportMode = ModelImporterMaterialImportMode.None;
                importer.SaveAndReimport();
            }
            
        }

        
        
        AssetDatabase.SaveAssets();
    }


    static private void GetDirFiles(string dirPath,List<string> fList)
    {
        if (!Directory.Exists(dirPath))
        {
            Debug.Log("文件夹不存在:" + dirPath);
            return;
        }

        string[] fileList = Directory.GetFileSystemEntries(dirPath);
        foreach (string file in fileList)
        {
            // 先当作目录处理如果存在这个目录就递归Copy该目录下面的文件
            if (Directory.Exists(file))
            {
                GetDirFiles(file, fList);
            }
            else
            {
                // 添加到数据里面
                if (file.Contains(".spriteatlas") || file.Contains(".meta"))
                {
                    continue;
                }

                fList.Add(file);
            }
        }
    }


    [MenuItem("Assets/资源/Find References", true)]
    static private bool VFind()
    {
        string path = AssetDatabase.GetAssetPath(Selection.activeObject);
        return (!string.IsNullOrEmpty(path));
    }

    static string GetRelativeAssetsPath(string path)
    {
        return "Assets" + Path.GetFullPath(path).Replace(Path.GetFullPath(Application.dataPath), "").Replace('\\', '/');
    }

    public static Object GetLogObject(Object asset)
    {
        return AssetDatabase.LoadAssetAtPath<Object>(GetRelativeAssetsPath(AssetDatabase.GetAssetPath(asset)));
    }

    public static Object GetLogObject(string path)
    {
        return AssetDatabase.LoadAssetAtPath<Object>(GetRelativeAssetsPath(path));
    }




    [MenuItem("便捷工具/资源操作/查找/查找预设中ParticleSystemRenderer.SortingLayer的值(预设资源)")]

    static void OnSearchLayer()
    {
        Debug.Log("开始!!!");
        Object[] SelectedAsset =
            Selection.GetFiltered(typeof(Object), SelectionMode.Assets & SelectionMode.ExcludePrefab);
        if (SelectedAsset.Length == 0)
        {
            Debug.LogError("您尚未选择资源!!!");
            return;

        }

        EditorUtility.DisplayProgressBar("Replacing...", "Start replace", 0);
        foreach (Object tmpFolder in SelectedAsset)
        {
            int progress = 0;
            progress++;

            string path = AssetDatabase.GetAssetPath(tmpFolder);
            string[] nameSplit = AssetDatabase.GetAssetPath(tmpFolder).Split('/');
            if (!string.IsNullOrEmpty(path))
            {
                string guid = AssetDatabase.AssetPathToGUID(path);
                EditorUtility.DisplayProgressBar("Replacing....", path, ((float) progress / SelectedAsset.Length));
                GameObject obj = AssetDatabase.LoadAssetAtPath(path, typeof(GameObject)) as GameObject;

                bool isChanged = false;
                ParticleSystemRenderer[] list = obj.GetComponentsInChildren<ParticleSystemRenderer>(true);
                foreach (ParticleSystemRenderer item in list)
                {
                    Debug.Log(nameSplit[nameSplit.Length - 1] + "/" + item.transform.name + "中的粒子层级:" +
                              item.sortingLayerName + "," + item.sortingOrder);
                    isChanged = true;
                }

                if (isChanged)
                {
                    EditorUtility.SetDirty(obj);
                }
            }
        }

        EditorUtility.ClearProgressBar();
        AssetDatabase.SaveAssets();
        Debug.Log("结束!!!");
    }

    [MenuItem("便捷工具/资源操作/查找/查找预设中ParticleSystemRenderer.SortingLayer>=5的对象")]

    static void OnSearchLayer1()
    {
        Debug.Log("开始!!!");
        Object[] SelectedAsset =
            Selection.GetFiltered(typeof(Object), SelectionMode.Assets & SelectionMode.ExcludePrefab);
        if (SelectedAsset.Length == 0)
        {
            Debug.LogError("您尚未选择资源!!!");
            return;

        }

        EditorUtility.DisplayProgressBar("Replacing...", "Start replace", 0);
        foreach (Object tmpFolder in SelectedAsset)
        {
            int progress = 0;
            progress++;

            string path = AssetDatabase.GetAssetPath(tmpFolder);
            string[] nameSplit = AssetDatabase.GetAssetPath(tmpFolder).Split('/');
            if (!string.IsNullOrEmpty(path))
            {
                string guid = AssetDatabase.AssetPathToGUID(path);
                EditorUtility.DisplayProgressBar("Replacing....", path, ((float) progress / SelectedAsset.Length));
                GameObject obj = AssetDatabase.LoadAssetAtPath(path, typeof(GameObject)) as GameObject;

                ParticleSystemRenderer[] list = obj.GetComponentsInChildren<ParticleSystemRenderer>(true);
                foreach (ParticleSystemRenderer item in list)
                {
                    if (item.sortingOrder >= 5)
                    {
                        Debug.Log(
                            nameSplit[nameSplit.Length - 1] + "/" + item.transform.name + "中的粒子层级:" +
                            item.sortingLayerName + "," + item.sortingOrder, item);
                    }
                }
            }
        }

        EditorUtility.ClearProgressBar();
        Debug.Log("结束!!!");
    }

    [MenuItem("便捷工具/资源操作/查找/查找预设中ParticleSystemRenderer.SortingLayer>5的对象,并赋值")]

    static void OnSetLayer1()
    {
        Debug.Log("开始!!!");
        Object[] SelectedAsset =
            Selection.GetFiltered(typeof(Object), SelectionMode.Assets & SelectionMode.ExcludePrefab);
        if (SelectedAsset.Length == 0)
        {
            Debug.LogError("您尚未选择资源!!!");
            return;

        }

        EditorUtility.DisplayProgressBar("Replacing...", "Start replace", 0);
        foreach (Object tmpFolder in SelectedAsset)
        {
            int progress = 0;
            progress++;

            string path = AssetDatabase.GetAssetPath(tmpFolder);
            string[] nameSplit = AssetDatabase.GetAssetPath(tmpFolder).Split('/');
            if (!string.IsNullOrEmpty(path))
            {
                string guid = AssetDatabase.AssetPathToGUID(path);
                EditorUtility.DisplayProgressBar("Replacing....", path, ((float) progress / SelectedAsset.Length));
                GameObject obj = AssetDatabase.LoadAssetAtPath(path, typeof(GameObject)) as GameObject;

                ParticleSystemRenderer[] list = obj.GetComponentsInChildren<ParticleSystemRenderer>(true);
                foreach (ParticleSystemRenderer item in list)
                {
                    if (item.sortingOrder >= 5)
                    {
                        int value = item.sortingOrder % 5;
                        item.sortingOrder = value == 0 ? 1 : value;
                        Debug.Log(
                            nameSplit[nameSplit.Length - 1] + "/" + item.transform.name + "中的粒子层级:" +
                            item.sortingLayerName + "," + item.sortingOrder, item);
                    }
                }
            }
        }

        EditorUtility.ClearProgressBar();
        AssetDatabase.SaveAssets();
        Debug.Log("结束!!!");
    }

    [MenuItem("便捷工具/资源操作/查找/替换预设中ParticleSystemRenderer.SortingLayer的值为Effect(预设资源)")]
    static void OnReplaceLayer_Effect()
    {
        Debug.Log("开始!!!");
        Object[] SelectedAsset =
            Selection.GetFiltered(typeof(Object), SelectionMode.Assets & SelectionMode.ExcludePrefab);
        if (SelectedAsset.Length == 0)
        {
            Debug.LogError("您尚未选择资源!!!");
            return;

        }

        EditorUtility.DisplayProgressBar("Replacing...", "Start replace", 0);
        foreach (Object tmpFolder in SelectedAsset)
        {
            int progress = 0;
            progress++;

            string path = AssetDatabase.GetAssetPath(tmpFolder);
            string[] nameSplit = AssetDatabase.GetAssetPath(tmpFolder).Split('/');
            if (!string.IsNullOrEmpty(path))
            {
                string guid = AssetDatabase.AssetPathToGUID(path);
                EditorUtility.DisplayProgressBar("Replacing....", path, ((float) progress / SelectedAsset.Length));
                GameObject obj = AssetDatabase.LoadAssetAtPath(path, typeof(GameObject)) as GameObject;

                bool isChanged = false;
                ParticleSystemRenderer[] list = obj.GetComponentsInChildren<ParticleSystemRenderer>(true);
                foreach (ParticleSystemRenderer item in list)
                {
                    if (!item.sortingLayerName.Equals("Effect"))
                    {
                        item.sortingLayerName = "Effect";
                        Debug.Log(nameSplit[nameSplit.Length - 1] + "/" + item.transform.name + "中的粒子层级:" +
                                  item.sortingLayerName);
                        isChanged = true;
                    }
                }

                if (isChanged)
                {
                    EditorUtility.SetDirty(obj);
                }
            }
        }

        EditorUtility.ClearProgressBar();
        AssetDatabase.SaveAssets();

        Debug.Log("结束!!!");
    }

    [MenuItem("便捷工具/资源操作/查找/替换预设中ParticleSystemRenderer.SortingLayer的值为Guide(预设资源)")]
    static void OnReplaceLayer_Guide()
    {
        Debug.Log("开始!!!");
        Object[] SelectedAsset =
            Selection.GetFiltered(typeof(Object), SelectionMode.Assets & SelectionMode.ExcludePrefab);
        if (SelectedAsset.Length == 0)
        {
            Debug.LogError("您尚未选择资源!!!");
            return;

        }

        EditorUtility.DisplayProgressBar("Replacing...", "Start replace", 0);
        foreach (Object tmpFolder in SelectedAsset)
        {
            int progress = 0;
            progress++;

            string path = AssetDatabase.GetAssetPath(tmpFolder);
            string[] nameSplit = AssetDatabase.GetAssetPath(tmpFolder).Split('/');
            if (!string.IsNullOrEmpty(path))
            {
                string guid = AssetDatabase.AssetPathToGUID(path);
                EditorUtility.DisplayProgressBar("Replacing....", path, ((float) progress / SelectedAsset.Length));
                GameObject obj = AssetDatabase.LoadAssetAtPath(path, typeof(GameObject)) as GameObject;

                bool isChanged = false;
                ParticleSystemRenderer[] list = obj.GetComponentsInChildren<ParticleSystemRenderer>(true);
                foreach (ParticleSystemRenderer item in list)
                {
                    if (!item.sortingLayerName.Equals("Guide"))
                    {
                        item.sortingLayerName = "Guide";
                        Debug.Log(nameSplit[nameSplit.Length - 1] + "/" + item.transform.name + "中的粒子层级:" +
                                  item.sortingLayerName);
                        isChanged = true;
                    }
                }

                if (isChanged)
                {
                    EditorUtility.SetDirty(obj);
                }
            }
        }

        EditorUtility.ClearProgressBar();
        AssetDatabase.SaveAssets();

        Debug.Log("结束!!!");
    }

    [MenuItem("便捷工具/资源操作/查找/替换预设中ParticleSystemRenderer.SortingLayer的值为UI(预设资源)")]
    static void OnReplaceLayer_UI()
    {
        Debug.Log("开始!!!");
        Object[] SelectedAsset =
            Selection.GetFiltered(typeof(Object), SelectionMode.Assets & SelectionMode.ExcludePrefab);
        if (SelectedAsset.Length == 0)
        {
            Debug.LogError("您尚未选择资源!!!");
            return;

        }

        EditorUtility.DisplayProgressBar("Replacing...", "Start replace", 0);
        foreach (Object tmpFolder in SelectedAsset)
        {
            int progress = 0;
            progress++;

            string path = AssetDatabase.GetAssetPath(tmpFolder);
            string[] nameSplit = AssetDatabase.GetAssetPath(tmpFolder).Split('/');
            if (!string.IsNullOrEmpty(path))
            {
                string guid = AssetDatabase.AssetPathToGUID(path);
                EditorUtility.DisplayProgressBar("Replacing....", path, ((float) progress / SelectedAsset.Length));
                GameObject obj = AssetDatabase.LoadAssetAtPath(path, typeof(GameObject)) as GameObject;

                bool isChanged = false;
                ParticleSystemRenderer[] list = obj.GetComponentsInChildren<ParticleSystemRenderer>(true);
                foreach (ParticleSystemRenderer item in list)
                {
                    if (!item.sortingLayerName.Equals("UI"))
                    {
                        item.sortingLayerName = "UI";
                        Debug.Log(nameSplit[nameSplit.Length - 1] + "/" + item.transform.name + "中的粒子层级:" +
                                  item.sortingLayerName);
                        isChanged = true;
                    }
                }

                if (isChanged)
                {
                    EditorUtility.SetDirty(obj);
                }
            }
        }

        EditorUtility.ClearProgressBar();
        AssetDatabase.SaveAssets();

        Debug.Log("结束!!!");
    }


    [MenuItem("GameObject/UI设置/清理Image和Text的碰撞", priority = 0)]
    public static void GeneratorLuaUICode()
    {
        var root = Selection.activeTransform;
        if (root != null)
        {
            var children = root.GetComponentsInChildren<Image>();
            foreach (var item in children)
            {
                item.raycastTarget = false;
            }

            var children2 = root.GetComponentsInChildren<Text>();
            foreach (var item in children2)
            {
                item.raycastTarget = false;
            }
        }
    }

    [MenuItem("GameObject/UI设置/设置Image和Text的碰撞", priority = 0)]
    public static void GeneratorLuaUICode2()
    {
        var root = Selection.activeTransform;
        if (root != null)
        {
            var children = root.GetComponentsInChildren<Image>();
            foreach (var item in children)
            {
                item.raycastTarget = true;
            }

            var children2 = root.GetComponentsInChildren<Text>();
            foreach (var item in children2)
            {
                item.raycastTarget = true;
            }
        }
    }

    [MenuItem("Packager/查找资源是否相同文件", false, 25)]
    static private void FindSameFileInProject()
    {
        Debug.Log("=======================start=============================");
        string[] files = Directory.GetFiles(Application.dataPath + "/GameAssets", "*.*", SearchOption.AllDirectories);
        Dictionary<string, List<string>> fileSameMd5Dic = new Dictionary<string, List<string>>();
        Dictionary<string, string> fileMd5Dic = new Dictionary<string, string>();
        int i = 0;
        foreach (var file in files)
        {
            i++;
            if (file.EndsWith(".meta") || file.EndsWith(".lua") || file.EndsWith(".bytes"))
                continue;
            string path = file.Replace('\\', '/');
            if (!path.Contains($"/GameAssets/"))
            {
                continue;
            }

            EditorUtility.DisplayProgressBar("匹配资源", $"正在检测{file}资源中...", 1.0f * i / files.Length);
            string md5 = MD5Util.Get(file);
            if (fileMd5Dic.ContainsKey(md5))
            {
                List<string> lst;
                if (!fileSameMd5Dic.TryGetValue(md5, out lst))
                {
                    lst = new List<string>();
                    lst.Add(fileMd5Dic[md5]);
                    fileSameMd5Dic.Add(md5, lst);
                }

                lst.Add(file);
                continue;
            }

            fileMd5Dic.Add(md5, file);
        }

        EditorUtility.ClearProgressBar();
        foreach (var kv in fileSameMd5Dic)
        {
            Debug.LogError("Start 相同文件..");
            foreach (var file in kv.Value)
            {
                Debug.LogError("    ->" + file);
            }

            Debug.LogError("End 相同文件..");
        }

        Debug.Log("=======================End=============================");
        if(fileMd5Dic.Count > 0)
        {
            SameMD5Data sameMD5Data = new SameMD5Data();
            sameMD5Data.fileSameMd5Dic = fileSameMd5Dic;
            sameMD5Data.Save();
        }
    }

    public static int IndexesOf(byte[] source, byte[] pattern)
    {
        int valueLength = source.Length;
        int patternLength = pattern.Length;

        if ((valueLength == 0) || (patternLength == 0) || (patternLength > valueLength))
        {
            return -1;
        }

        var badCharacters = new int[256];

        for (var i = 0; i < 256; i++)
        {
            badCharacters[i] = patternLength;
        }

        var lastPatternByte = patternLength - 1;

        for (int i = 0; i < lastPatternByte; i++)
        {
            badCharacters[pattern[i]] = lastPatternByte - i;
        }

        int index = 0;

        while (index <= valueLength - patternLength)
        {
            for (var i = lastPatternByte; source[index + i] == pattern[i]; i--)
            {
                if (i == 0)
                {
                    return index;
                    break;
                }
            }

            index += badCharacters[source[index + lastPatternByte]];
        }

        return -1;
    }

    [MenuItem("Assets/资源/清理无用的材质球属性", false, 26)]
    public static void ClearMaterialProperties()
    {
        UnityEngine.Object[] objs = Selection.GetFiltered(typeof(Material), SelectionMode.DeepAssets);
        for (int i = 0; i < objs.Length; i++)
        {
            EditorUtility.DisplayProgressBar("清理中...", objs[i].name, i / objs.Length);
            Material mat = objs[i] as Material;
            if (mat)
            {
                SerializedObject psSource = new SerializedObject(mat);
                SerializedProperty emissionProperty = psSource.FindProperty("m_SavedProperties");
                SerializedProperty texEnvs = emissionProperty.FindPropertyRelative("m_TexEnvs");
                string log = string.Empty;
                if (CleanMaterialSerializedProperty(texEnvs, mat, ref log))
                {
                    Debug.LogError("Clean useless texture properties->" + mat.name  + "\n" + log, GetLogObject(mat));
                }
                else
                {
                    Debug.Log("Not clean useless texture properties->" + mat.name + "\n" + log, GetLogObject(mat));
                }
                psSource.ApplyModifiedProperties();
                EditorUtility.SetDirty(mat);
            }
        }
        AssetDatabase.SaveAssets();
        EditorUtility.ClearProgressBar();
    }

    private static bool CleanMaterialSerializedProperty(SerializedProperty property, Material mat,ref string log)
    {
        bool res = false;
        for (int j = property.arraySize - 1; j >= 0; j--)
        {
            string propertyName = property.GetArrayElementAtIndex(j).FindPropertyRelative("first").stringValue;
            if (!mat.HasProperty(propertyName))
            {
                if (propertyName == "_MainTex")
                {
                    if (property.GetArrayElementAtIndex(j).FindPropertyRelative("second").FindPropertyRelative("m_Texture").objectReferenceValue != null)
                    {
                        property.GetArrayElementAtIndex(j).FindPropertyRelative("second").FindPropertyRelative("m_Texture").objectReferenceValue = null;
                        res = true;
                    }
                }
                else
                {
                    property.DeleteArrayElementAtIndex(j);
                    log += "Delete legacy property in serialized object:" + propertyName + "\n";
                    res = true;
                }
            }
        }
        return res;
    }
}

public class SameMD5Data
{
    public Dictionary<string, List<string>> fileSameMd5Dic = new Dictionary<string, List<string>>();

    public void Save()
    {
        int i = Application.dataPath.LastIndexOf('/');
        string path = $"{Application.dataPath.Substring(0, i + 1)}BuildAssetLog";
        if (!Directory.Exists(path))
        {
            Directory.CreateDirectory(path);
        }
        string filePath = $"{path}/SameMD5AssetsLog.json";
        using (StreamWriter sw = new StreamWriter(filePath, false))
        {
            string json = JsonConvert.SerializeObject(this, Formatting.Indented);
            sw.WriteLine(json);
            sw.Dispose();
        }
    }
}
